<?php

declare(strict_types=1);
/**
 * This file is part of MoChat.
 * @link     https://mo.chat
 * @document https://mochat.wiki
 * @contact  group@mo.chat
 * @license  https://github.com/mochat-cloud/mochat/blob/master/LICENSE
 */
namespace MoChat\Plugin\ContactStage\Action\Dashboard;

use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\Middleware;
use Hyperf\HttpServer\Annotation\Middlewares;
use Hyperf\HttpServer\Annotation\RequestMapping;
use MoChat\App\Common\Middleware\DashboardAuthMiddleware;
use MoChat\App\Rbac\Middleware\PermissionMiddleware;
use MoChat\App\WorkContact\Constants\AddWay;
use MoChat\App\WorkContact\Contract\WorkContactContract;
use MoChat\App\WorkContact\Contract\WorkContactEmployeeContract;
use MoChat\App\WorkContact\Contract\WorkContactTagContract;
use MoChat\App\WorkContact\Contract\WorkContactTagPivotContract;
use MoChat\App\WorkEmployee\Contract\WorkEmployeeContract;
use MoChat\Framework\Action\AbstractAction;
use MoChat\Framework\Constants\ErrorCode;
use MoChat\Framework\Exception\CommonException;
use MoChat\Framework\Request\ValidateSceneTrait;
use MoChat\Plugin\ContactStage\Contract\ContactStageEmployeeContract;

/**
 * 客户阶段管理-未设置客户.
 *
 * Class NotSetContact.
 * @Controller
 */
class NotSetContact extends AbstractAction
{
    use ValidateSceneTrait;

    /**
     * 客户表.
     * @Inject
     * @var WorkContactContract
     */
    private $workContactService;

    /**
     * 员工 - 客户关联.
     * @Inject
     * @var WorkContactEmployeeContract
     */
    private $workContactEmployeeService;

    /**
     * 客户 - 阶段关联.
     * @Inject
     * @var ContactStageEmployeeContract
     */
    private $contactStageEmployeeService;

    /**
     * 标签.
     * @Inject
     * @var WorkContactTagContract
     */
    private $workContactTagService;

    /**
     * 客户 - 标签关联.
     * @Inject
     * @var WorkContactTagPivotContract
     */
    private $workContactTagPivotService;

    /**
     * 员工.
     * @Inject
     * @var WorkEmployeeContract
     */
    private $workEmployeeService;

    /**
     * @RequestMapping(path="/dashboard/contactStage/notSetContact", methods="GET")
     * @Middlewares({
     *     @Middleware(DashboardAuthMiddleware::class),
     *     @Middleware(PermissionMiddleware::class)
     * })
     * @return array 返回数组
     */
    public function handle(): array
    {
        $user = user();
        // 判断用户绑定企业信息
        if (! isset($user['corpIds']) || count($user['corpIds']) !== 1) {
            throw new CommonException(ErrorCode::INVALID_PARAMS, '未选择登录企业，不可操作');
        }

        // 接收参数
        $params = [
            'tagIds' => $this->request->input('tagIds', []),
            'employeeId' => (int) $this->request->input('employeeId', 0),
            'name' => $this->request->input('name'),
            'startTime' => $this->request->input('startTime'),
            'endTime' => $this->request->input('endTime'),
            'addWay' => (int) $this->request->input('addWay'),
            'page' => $this->request->input('page', 1),
            'perPage' => $this->request->input('perPage', '10'),
        ];
        $params['corpId'] = $user['corpIds'][0];

        // 处理查询条件
        $where = $this->handleWhere($params);

        return $this->handleContactList($where, $params);
    }

    /**
     * 验证规则.
     *
     * @return array 响应数据
     */
    protected function rules(): array
    {
        return [];
    }

    /**
     * 验证错误提示.
     * @return array 响应数据
     */
    protected function messages(): array
    {
        return [];
    }

    private function handleWhere(array $params): array
    {
        $where['corpId'] = $params['corpId'];
        ! empty($params['employeeId']) && $where['employeeId'] = $params['employeeId'];
        // 添加时间搜索
        ! empty($params['startTime']) && $where['startTime'] = $params['startTime'];
        ! empty($params['endTime']) && $where['endTime'] = $params['endTime'];
        ! empty($params['addWay']) && $where['endTime'] = $params['addWay'];
        $contactStage = $this->contactStageEmployeeService->getContactStageEmployeeByCorpId($params['corpId'], ['contact_id', 'employee_id']);
        $list1 = [];
        foreach ($contactStage as $item) {
            $list1[$item['contactId'] . '_' . $item['employeeId']] = $item;
        }
        $contactEmployee = $this->workContactEmployeeService->getWorkContactEmployeesByCorpId($params['corpId'], ['id', 'contact_id', 'employee_id']);
        foreach ($contactEmployee as $key => $val) {
            if (! empty($list1[$val['contactId'] . '_' . $val['employeeId']])) {
                unset($contactEmployee[$key]);
            }
        }
        $ids = array_column($contactEmployee, 'id');
        $where['ids'] = $ids;
        $contactIds = array_unique(array_column($contactEmployee, 'contactId'));
        $where['contactId'] = $contactIds;
        // 企业标签搜索
        if (! empty($params['tagIds'])) {
            // 查询在标签里的客户id
            $tagPivot = $this->workContactTagPivotService->getWorkContactTagPivotsByContactTagIdsType($params['tagIds'], 1, $contactIds, ['contact_id']);
            if (! empty($tagPivot)) {
                $contactIds = array_unique(array_column($tagPivot, 'contactId'));
                // 取交集
                $where['contactId'] = array_intersect($where['contactId'], $contactIds);
                $ids = $this->getContactEmployeeIds($contactIds, $params['tagIds']);
                empty($ids) || $where['ids'] = $ids;
            }
        }
        // 客户名称搜索
        if (! empty($params['name'])) {
            $contacts = $this->workContactService->getWorkContactsByIdsName($where['contactId'], $params['name'], ['id']);
            if (empty($contacts)) {
                return [];
            }
            $contactIds = array_column($contacts, 'id');
            $where['contactId'] = $contactIds;
        }
        return $where;
    }

    private function handleContactList(array $where, array $params): array
    {
        $data = [
            'page' => [
                'perPage' => 20,
                'total' => 0,
                'totalPage' => 0,
            ],
            'list' => [],
        ];
        $columns = [
            'id',
            'employee_id',
            'contact_id',
            'remark',
            'create_time',
            'add_way',
            'status',
        ];

        // 查询数据
        $list = $this->workContactEmployeeService->getWorkContactEmployeeIndex(
            $where,
            $columns,
            (int) $params['perPage'],
            (int) $params['page']
        );

        if (empty($list['data'])) {
            return $data;
        }

        // 客户id
        $contactIds = array_unique(array_column($list['data'], 'contactId'));
        // 员工id
        $employeeIds = array_unique(array_column($list['data'], 'employeeId'));
        // 查询客户基础信息
        $contact = $this->getContactInfo($contactIds);
        // 查询客户归属成员信息
        $employee = $this->getEmployee($employeeIds);

        foreach ($list['data'] as &$raw) {
            $raw['addWayText'] = AddWay::$Enum[$raw['addWay']] ?? '';
            $raw['name'] = '';
            $raw['avatar'] = '';
            if (isset($contact[$raw['contactId']])) {
                $raw['name'] = $contact[$raw['contactId']]['name'];
                $raw['avatar'] = $contact[$raw['contactId']]['avatar'] ? file_full_url($contact[$raw['contactId']]['avatar']) : $contact[$raw['contactId']]['avatar'];
            }

            $raw['employeeName'] = [];
            if (isset($employee[$raw['employeeId']])) {
                $raw['employeeName'] = $employee[$raw['employeeId']]['name'];
            }

            // 查询客户标签
            $raw['tag'] = $this->getContactTag($raw['contactId'], $raw['employeeId']);
        }
        unset($raw);

        // 返回数据
        $data = [
            'page' => [
                'perPage' => $list['per_page'] ?? 20,
                'total' => $list['total'] ?? 0,
                'totalPage' => $list['last_page'] ?? 0,
            ],
            'list' => empty($list['data']) ? [] : $list['data'],
        ];

        return $data;
    }

    /**
     * 获取客户信息.
     * @param $contactIds
     */
    private function getContactInfo($contactIds): array
    {
        $contact = $this->workContactService->getWorkContactsById($contactIds);
        if (! empty($contact)) {
            $contact = array_column($contact, null, 'id');
        }

        return $contact;
    }

    /**
     * 查询员工信息.
     * @param $employeeIds
     */
    private function getEmployee($employeeIds): array
    {
        // 根据员工id查询员工信息、企业id
        $employeeInfo = $this->workEmployeeService->getWorkEmployeesById($employeeIds, ['id', 'name', 'corp_id']);

        if (empty($employeeInfo)) {
            return [];
        }

        return array_column($employeeInfo, null, 'id');
    }

    /**
     * 获取客户标签.
     * @param $contactId
     * @param $employeeId
     */
    private function getContactTag($contactId, $employeeId): array
    {
        $contactTag = $this->workContactTagPivotService->getWorkContactTagPivotsByOtherId($contactId, $employeeId);
        if (empty($contactTag)) {
            return [];
        }

        $tagIds = array_unique(array_column($contactTag, 'contactTagId'));
        // 根据标签id查询标签名称
        $tagInfo = $this->workContactTagService->getWorkContactTagsById($tagIds, ['id', 'name']);

        if (empty($tagInfo)) {
            return [];
        }

        $tagInfo = array_column($tagInfo, null, 'id');

        $tagName = [];
        foreach ($contactTag as &$raw) {
            if (isset($tagInfo[$raw['contactTagId']])) {
                $tagName[] = $tagInfo[$raw['contactTagId']]['name'];
            }
        }
        unset($raw);

        return array_unique($tagName);
    }

    private function getContactEmployeeIds(array $contactIds, array $tagIds): array
    {
        $contactEmployees = $this->workContactEmployeeService->getWorkContactEmployeesByContactIds($contactIds, ['id', 'employee_id', 'contact_id']);
        foreach ($contactEmployees as $key => $val) {
            $contactTags = $this->workContactTagPivotService->getWorkContactTagPivotsByContactIdsEmployeeIdsTagIds([$val['contactId']], [$val['employeeId']], $tagIds, 1);
            if (empty($contactTags)) {
                unset($contactEmployees[$key]);
            }
        }
        if (empty($contactEmployees)) {
            return [];
        }
        return array_column($contactEmployees, 'id');
    }
}
